use axum::{
    response::{IntoResponse, Json},
    extract::{Query},
    http::{StatusCode},
};
use serde::{Deserialize, Serialize};
use serde_json::{json, Value};
use std::{
    collections::HashMap,
    path::{PathBuf},
    fs,
    io::{self, Read},
};
use uuid::Uuid;
use chrono::prelude::*;
use md5;


// 配置根目录
const ROOT_DIR: &str = "./data"; // 注意：确保这个目录存在

// 自定义错误类型
#[derive(Debug)]
pub enum ElfinderError {
    IoError(io::Error),
    InvalidPath,
     #[allow(dead_code)] // 抑制未使用警告
    InvalidHash,
    FileExists,
     #[allow(dead_code)] // 抑制未使用警告
    DirectoryNotEmpty,
    UnknownCommand(String),
}

impl From<io::Error> for ElfinderError {
    fn from(err: io::Error) -> Self {
        ElfinderError::IoError(err)
    }
}

impl IntoResponse for ElfinderError {
    fn into_response(self) -> axum::response::Response {
        let (status, error_message) = match self {
            ElfinderError::IoError(err) => (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()),
            ElfinderError::InvalidPath => (StatusCode::BAD_REQUEST, "无效路径".to_string()),
            ElfinderError::InvalidHash => (StatusCode::BAD_REQUEST, "无效哈希值".to_string()),
            ElfinderError::FileExists => (StatusCode::CONFLICT, "文件已存在".to_string()),
            ElfinderError::DirectoryNotEmpty => (StatusCode::CONFLICT, "目录不为空".to_string()),
            ElfinderError::UnknownCommand(cmd) => (StatusCode::BAD_REQUEST, format!("未知命令: {}", cmd)),
        };
        
        (status, Json(json!({ "error": error_message }))).into_response()
    }
}

// 响应结构
#[derive(Serialize)]
struct ElfinderResponse {
    #[serde(skip_serializing_if = "Option::is_none")]
    cwd: Option<Cwd>,
    #[serde(skip_serializing_if = "Option::is_none")]
    files: Option<Vec<ElFile>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    added: Option<Vec<ElFile>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    changed: Option<Vec<ElFile>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    removed: Option<Vec<String>>,
    #[serde(skip_serializing_if = "Option::is_none")]
    content: Option<String>,
    #[serde(skip_serializing_if = "HashMap::is_empty")]
    options: HashMap<String, String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    error: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")]
    warning: Option<String>,
    api: u8,
    #[serde(rename = "uploadMaxSize")]
    upload_max_size: String,
}

#[derive(Serialize)]
struct Cwd {
    name: String,
    hash: String,
    mime: String,
    size: u64,
    date: String,
    path: String,
    #[serde(rename = "phash")]
    parent_hash: String,
    volumeid: String,
}

#[derive(Serialize, Debug)]
struct ElFile {
    hash: String,
    name: String,
    mime: String,
    size: u64,
    date: String,
    read: u8,
    write: u8,
    locked: u8,
    hidden: u8,
    #[serde(rename = "isdir")]
    is_dir: u8,
    dim: Option<String>,
    volumeid: String,
    #[serde(rename = "phash")]
    parent_hash: String,
    #[serde(rename = "hasThumb")]
    has_thumb: u8,
}

// 请求参数
#[derive(Deserialize, Debug)]
pub struct RequestParams {
    cmd: String,
    target: Option<String>,
    targets: Option<Vec<String>>,
    name: Option<String>,
    width: Option<u32>,
    height: Option<u32>,
}

// 生成文件哈希
fn get_hash<P: AsRef<std::path::Path>>(path: P) -> String {
    let path_str = path.as_ref().to_string_lossy().into_owned();
    let digest = md5::compute(path_str);
    format!("{:x}", digest)
}

// 生成卷ID
fn get_volume_id() -> String {
    Uuid::new_v4().to_string()
}

// 从哈希获取路径
fn path_from_hash(hash: &str) -> Result<PathBuf, ElfinderError> {
    // 这里是简化的实现，实际中可能需要更复杂的映射
    if hash.is_empty() {
        return Ok(PathBuf::from(ROOT_DIR));
    }
    
    // 假设哈希是基于完整路径生成的，这里需要反向映射
    // 实际应用中可能需要维护哈希到路径的映射表
    let root = PathBuf::from(ROOT_DIR);
    
    // 简单示例：从哈希中恢复路径（这需要根据你的哈希生成方式调整）
    // 这里假设哈希是路径的MD5值，这是一个简化的示例
    // 实际中你可能需要更复杂的映射机制
    Ok(root)
}

// 获取文件信息
fn get_file_info(path: &PathBuf) -> Result<ElFile, ElfinderError> {
    let metadata = fs::metadata(path)?;
    let modified = metadata.modified()?;
    let datetime: DateTime<Local> = modified.into();
    
    let is_dir = metadata.is_dir();
    let mime = if is_dir {
        "directory".to_string()
    } else {
        "file".to_string() // 实际中应该使用mime_guess等库
    };
    
    let file_name = path.file_name()
        .unwrap_or_default()
        .to_string_lossy()
        .into_owned();
    
    let parent = path.parent().unwrap_or(std::path::Path::new("/"));
    let parent_hash = get_hash(parent);
    
    Ok(ElFile {
        hash: get_hash(path),
        name: file_name,
        mime,
        size: if is_dir { 0 } else { metadata.len() },
        date: datetime.format("%Y-%m-%d %H:%M").to_string(),
        read: 1,
        write: 1,
        locked: 0,
        hidden: 0,
        is_dir: is_dir as u8,
        dim: None,
        volumeid: get_volume_id(),
        parent_hash,
        has_thumb: 0,
    })
}

// 获取目录内容
fn get_dir_content(path: &PathBuf) -> Result<Vec<ElFile>, ElfinderError> {
    let mut files = vec![];
    
    if path.is_dir() {
        for entry in fs::read_dir(path)? {
            let entry = entry?;
            let file_path = entry.path();
            files.push(get_file_info(&file_path)?);
        }
    }
    
    Ok(files)
}

// 主处理函数
pub async fn elfinder_handler(Query(params): Query<RequestParams>) -> Result<Json<Value>, ElfinderError> {
    match params.cmd.as_str() {
        "open" => handle_open(&params.target).await,
        "ls" => handle_ls(&params.target).await,
        "mkfile" => handle_mkfile(&params.target, &params.name).await,
        "mkdir" => handle_mkdir(&params.target, &params.name).await,
        "rename" => handle_rename(&params.target, &params.name).await,
        "upload" => handle_upload().await, // 上传处理函数需要完整的params
        "info" => handle_info(&params.target).await,
        "get" => handle_get(&params.target).await,
        "archive" => handle_archive().await,
        "extract" => handle_extract().await,
        "resize" => handle_resize().await,
        _ => Err(ElfinderError::UnknownCommand(params.cmd)),
    }
}

// 处理打开目录
async fn handle_open(target: &Option<String>) -> Result<Json<Value>, ElfinderError> {
    let path = match target {
        Some(hash) => path_from_hash(hash)?,
        None => PathBuf::from(ROOT_DIR),
    };
    
    let metadata = fs::metadata(&path)?;
    let modified = metadata.modified()?;
    let datetime: DateTime<Local> = modified.into();
    
    let parent = path.parent().unwrap_or(std::path::Path::new("/"));
    let parent_hash = get_hash(parent);
    
    let files = if metadata.is_dir() {
        get_dir_content(&path)?
    } else {
        vec![]
    };
    
    let cwd = Cwd {
        name: path.file_name().unwrap_or_default().to_string_lossy().into_owned(),
        hash: get_hash(&path),
        mime: "directory".to_string(),
        size: 0,
        date: datetime.format("%Y-%m-%d %H:%M").to_string(),
        path: path.to_string_lossy().into_owned(),
        parent_hash,
        volumeid: get_volume_id(),
    };
    
    let response = ElfinderResponse {
        cwd: Some(cwd),
        files: Some(files),
        added: None,
        changed: None,
        removed: None,
        content: None,
        options: HashMap::new(),
        error: None,
        warning: None,
        api: 2,
        upload_max_size: "128M".to_string(),
    };
    
    Ok(Json(json!(response)))
}

// 处理列出目录
async fn handle_ls(target: &Option<String>) -> Result<Json<Value>, ElfinderError> {
    handle_open(target).await
}

// 处理创建文件
async fn handle_mkfile(target: &Option<String>, name: &Option<String>) -> Result<Json<Value>, ElfinderError> {
    let parent_path = match target {
        Some(hash) => path_from_hash(hash)?,
        None => PathBuf::from(ROOT_DIR),
    };
    
    let file_name = name.as_ref().ok_or(ElfinderError::InvalidPath)?;
    let new_path = parent_path.join(file_name);
    
    if new_path.exists() {
        return Err(ElfinderError::FileExists);
    }
    
    // 创建空文件
    fs::File::create(&new_path)?;
    
    // 返回新创建的文件信息
    let new_file = get_file_info(&new_path)?;
    
    let response = ElfinderResponse {
        cwd: None,
        files: None,
        added: Some(vec![new_file]),
        changed: None,
        removed: None,
        content: None,
        options: HashMap::new(),
        error: None,
        warning: None,
        api: 2,
        upload_max_size: "128M".to_string(),
    };
    
    Ok(Json(json!(response)))
}

// 处理创建目录
async fn handle_mkdir(target: &Option<String>, name: &Option<String>) -> Result<Json<Value>, ElfinderError> {
    let parent_path = match target {
        Some(hash) => path_from_hash(hash)?,
        None => PathBuf::from(ROOT_DIR),
    };
    
    let dir_name = name.as_ref().ok_or(ElfinderError::InvalidPath)?;
    let new_path = parent_path.join(dir_name);
    
    if new_path.exists() {
        return Err(ElfinderError::FileExists);
    }
    
    // 创建目录
    fs::create_dir(&new_path)?;
    
    // 返回新创建的目录信息
    let new_dir = get_file_info(&new_path)?;
    
    let response = ElfinderResponse {
        cwd: None,
        files: None,
        added: Some(vec![new_dir]),
        changed: None,
        removed: None,
        content: None,
        options: HashMap::new(),
        error: None,
        warning: None,
        api: 2,
        upload_max_size: "128M".to_string(),
    };
    
    Ok(Json(json!(response)))
}

// 处理重命名
async fn handle_rename(target: &Option<String>, name: &Option<String>) -> Result<Json<Value>, ElfinderError> {
    let old_path = match target {
        Some(hash) => path_from_hash(hash)?,
        None => return Err(ElfinderError::InvalidPath),
    };
    
    let new_name = name.as_ref().ok_or(ElfinderError::InvalidPath)?;
    
    let parent = old_path.parent().ok_or(ElfinderError::InvalidPath)?;
    let new_path = parent.join(new_name);
    
    if new_path.exists() {
        return Err(ElfinderError::FileExists);
    }
    
    // 重命名文件/目录
    fs::rename(&old_path, &new_path)?;
    
    // 返回修改后的文件信息
    let changed_file = get_file_info(&new_path)?;
    
    let response = ElfinderResponse {
        cwd: None,
        files: None,
        added: None,
        changed: Some(vec![changed_file]),
        removed: None,
        content: None,
        options: HashMap::new(),
        error: None,
        warning: None,
        api: 2,
        upload_max_size: "128M".to_string(),
    };
    
    Ok(Json(json!(response)))
}

// 处理上传（需要完整的params，因为使用Multipart）
async fn handle_upload() -> Result<Json<Value>, ElfinderError> {
    // 注意：这个实现需要使用Multipart，需要修改路由处理函数
    // 这里只是示例，实际实现需要处理上传的文件
    Err(ElfinderError::UnknownCommand("upload".to_string()))
}

// 处理获取文件信息
async fn handle_info(target: &Option<String>) -> Result<Json<Value>, ElfinderError> {
    let path = match target {
        Some(hash) => path_from_hash(hash)?,
        None => return Err(ElfinderError::InvalidPath),
    };
    
    let file_info = get_file_info(&path)?;
    
    let response = ElfinderResponse {
        cwd: None,
        files: Some(vec![file_info]),
        added: None,
        changed: None,
        removed: None,
        content: None,
        options: HashMap::new(),
        error: None,
        warning: None,
        api: 2,
        upload_max_size: "128M".to_string(),
    };
    
    Ok(Json(json!(response)))
}

// 处理获取文件内容
async fn handle_get(target: &Option<String>) -> Result<Json<Value>, ElfinderError> {
    let path = match target {
        Some(hash) => path_from_hash(hash)?,
        None => return Err(ElfinderError::InvalidPath),
    };
    
    if path.is_dir() {
        return Err(ElfinderError::InvalidPath);
    }
    
    let mut file = fs::File::open(&path)?;
    let mut content = String::new();
    file.read_to_string(&mut content)?;
    
    let response = ElfinderResponse {
        cwd: None,
        files: None,
        added: None,
        changed: None,
        removed: None,
        content: Some(content),
        options: HashMap::new(),
        error: None,
        warning: None,
        api: 2,
        upload_max_size: "128M".to_string(),
    };
    
    Ok(Json(json!(response)))
}

// 处理归档
async fn handle_archive() -> Result<Json<Value>, ElfinderError> {
    // 注意：归档功能需要压缩库支持
    // 这里只是示例，实际实现需要使用压缩库
    Err(ElfinderError::UnknownCommand("archive".to_string()))
}

// 处理解压缩
async fn handle_extract() -> Result<Json<Value>, ElfinderError> {
    // 注意：解压缩功能需要压缩库支持
    // 这里只是示例，实际实现需要使用压缩库
    Err(ElfinderError::UnknownCommand("extract".to_string()))
}

// 处理调整大小（图片）
async fn handle_resize() -> Result<Json<Value>, ElfinderError> {
    // 注意：调整大小功能需要图像处理库支持
    // 这里只是示例，实际实现需要使用图像处理库
    Err(ElfinderError::UnknownCommand("resize".to_string()))
}
